import {detailDataType, getAsVal} from '../utils/util';
import {validatenull} from '../utils/validate';
import {DIC_PROPS} from '../global/variable'

const key = 'key';

function getDataType(list = [], props = {}, type) {
    let valueKey = props.value || DIC_PROPS.value;
    let childrenKey = props.children || DIC_PROPS.children;
    list.forEach(ele => {
        ele[valueKey] = detailDataType(ele[valueKey], type);
        if (ele[childrenKey]) getDataType(ele[childrenKey], props, type);
    });
    return list;
};

function getResData(data, props, dataType) {
    const bind = props.res
    let res = data;
    let deep = data.data;
    if (bind) {
        res = getAsVal(res, bind)
    } else if (deep) {
        res = Array.isArray(deep) ? deep : [deep]
    }
    if (dataType) res = getDataType(res, props, dataType)
    return res;
}

/**
 * 加载级联字典
 * @param columnOption
 * @param safe
 * @returns {Promise<unknown>}
 */
export const loadCascaderDic = (columnOption, safe) => {
    return new Promise(resolve => {
        let list = [];
        let result = {};
        let columnList = columnOption.filter(ele => ele.parentProp)
        safe.data.forEach((ele, index) => {
            if (!safe.cascaderDIC[index]) safe.cascaderDIC[index] = {}
            columnList.forEach(column => {
                if (column.hide !== true && column.dicFlag !== false) {
                    list.push(new Promise(resolve => {
                        if (ele[column.parentProp]) {
                            sendDic({
                                url: column.dicUrl,
                                props: column.props,
                                method: column.dicMethod,
                                headers: column.dicHeaders,
                                formatter: column.dicFormatter,
                                query: column.dicQuery,
                                dataType: column.dataType,
                                form: ele,
                                value: ele[column.parentProp]
                            }).then(res => {
                                let obj = {
                                    prop: column.prop,
                                    data: res,
                                    index: index
                                }
                                safe.cascaderDIC[index][obj.prop] = obj.data
                                resolve(obj);
                            });
                        } else {
                            let obj = {
                                prop: column.prop,
                                data: [],
                                index: index
                            }
                            safe.cascaderDIC[index][obj.prop] = obj.data
                            resolve(obj);
                        }
                    }));
                }
            });
        });
        Promise.all(list).then(data => {
            data.forEach(ele => {
                if (!result[ele.index]) result[ele.index] = {};
                result[ele.index][ele.prop] = ele.data;
            });
            resolve(result);
        });
    });
};
/**
 * 加载字典
 * @param option avueOption配置信息
 * @param safe  当前avue的对象实例
 * @returns {Promise<void>}
 */
export const loadDic = async (option, safe) => {
    const promises = [];
    const {column = []} = option;
    const notList = new Set(column.flatMap(col => col.cascader || []));
    let requestData;
    for (const col of column) {
        const {dicUrl, prop, parentProp, dicFlag, lazy} = col;

        if (!dicUrl || parentProp || dicFlag === false || lazy || notList.has(prop)) {
            continue;
        }
        requestData = {}

        requestData.url = dicUrl;
        requestData.name = prop;
        requestData.method = col.dicMethod;
        requestData.headers = col.dicHeaders;
        requestData.formatter = col.dicFormatter;
        requestData.props = col.props;
        requestData.dataType = col.dataType;
        requestData.query = col.dicQuery
        promises.push(sendDic(requestData).then(res => ({[prop]: res})));
    }

    const results = await Promise.all(promises);
    for (const result of results) {
        Object.assign(safe.DIC, result)
    }
    results.forEach(resultPart => Object.assign(safe.DIC, resultPart));
};
/**
 * 加载本地字典
 * @param option avueOption配置信息
 * @param safe   当前avue的对象实例
 * @returns {*}
 */
export const loadLocalDic = (option, safe) => {
    const columnData = option.column.reduce((acc, col) => {
        if (col.dicData) acc[col.prop] = getDataType(col.dicData, col.props, col.dataType);
        return acc;
    }, {});

    const result = {...option.dicData, ...columnData};

    Object.entries(result).forEach(([key, value]) => {
        safe.DIC[key] = value;
    });

    return result;
};

export const sendDic = (params) => {
    let {url, query, method, props, formatter, headers, value, column = {}, form = {}, dataType} = params;
    url = column.dicUrl || url;
    method = (column.dicMethod || method || 'get').toLowerCase();
    headers = column.dicHeaders || headers || {}
    query = column.dicQuery || query || {};
    formatter = column.dicFormatter || formatter;
    props = column.props || props || {};
    let list = url.match(/[^\{\}]+(?=\})/g) || []
    list.forEach(ele => {
        let result = ele === key ? value : form[ele]
        if (validatenull(result)) result = ''
        url = url.replace(`{{${ele}}}`, result);
    });

    const getKey = (data) => {
        let result = {};
        Object.keys(data).forEach(ele => {
            let eleKey = data[ele];
            if (typeof (eleKey) == 'string' && eleKey.match(/\{{|}}/g)) {
                let prop = eleKey.replace(/\{{|}}/g, '');
                result[ele] = prop == key ? value : form[prop]
            } else {
                result[ele] = eleKey;
            }
        });
        return result;
    }

    return new Promise((resolve, reject) => {
        if (!url) resolve([])
        const callback = (res) => {
            let list = [];
            res = res.data || {};
            if (typeof formatter === 'function') {
                list = formatter(res, form);
            } else {
                list = getResData(res, props, dataType);
            }
            resolve(list);
        };
        const getData = () => {
            let data = getKey(query);
            if (method === 'get') return {params: data}
            return {data}
        }
        window.axios(Object.assign({
            url,
            method,
            headers: getKey(headers),
        }, getData())).then(function (res) {
            callback(res);
        }).catch(err => [
            reject(err)
        ]);
    });
};